[CCR] Migrate to TS#260601
Conversation
|
@coderabbitai full review |
|
🧠 Learnings used✅ Actions performedFull review triggered. |
|
Just FYI for future @mentions, I'm I've completed the review. You can view the results here: |
|
🧠 Learnings used✅ Actions performedFull review triggered. |
📝 WalkthroughWalkthroughThis pull request completes a TypeScript migration of the Cross-Cluster Replication plugin codebase. JavaScript files across client-integration tests, fixtures, helpers, components, services, and Redux store management are converted to TypeScript with explicit type annotations. PropTypes-based runtime validation is replaced with TypeScript interfaces for React components. Service modules gain typed function signatures, Redux actions and reducers are reimplemented with full type coverage, and HTTP mocking utilities transition from JavaScript to a typed module. Test helpers introduce structured return types, and mock factories adopt partial parameter patterns to support optional fields. ✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
x-pack/platform/plugins/private/cross_cluster_replication/public/app/components/form_entry_row.tsx (1)
143-149: Redundant ternary branch.Lines 146-148:
Array.isArray(error) ? error : errorevaluates toerrorregardless of the condition.Suggested simplification
error={ - (structured && structured.message !== undefined - ? structured.message - : Array.isArray(error) - ? error - : error) as ReactNode + ((structured?.message !== undefined ? structured.message : error) as ReactNode) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@x-pack/platform/plugins/private/cross_cluster_replication/public/app/components/form_entry_row.tsx` around lines 143 - 149, The ternary in the error prop inside FormEntryRow is redundant: the inner branch `Array.isArray(error) ? error : error` always yields `error`; update the expression in the component (the variables `structured` and `error` in form_entry_row.tsx, where the prop `error={... as ReactNode}` is set) to simply choose `structured.message` when present and otherwise `error` (e.g., use a single conditional: structured && structured.message !== undefined ? structured.message : error) and keep the ReactNode cast as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/follower_index_default_settings.ts`:
- Around line 16-18: The check `if (!FOLLOWER_INDEX_ADVANCED_SETTINGS[name])`
treats valid falsy defaults (0, false, '') as missing keys; change the existence
check to explicitly test for presence (e.g., use
Object.prototype.hasOwnProperty.call(FOLLOWER_INDEX_ADVANCED_SETTINGS, name) or
(name in FOLLOWER_INDEX_ADVANCED_SETTINGS)) so that functions like
isSettingDefault and areAllSettingsDefault correctly recognize keys whose
defaults are falsy while still throwing for truly unknown setting names.
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.ts`:
- Around line 13-17: The defaulting of keyProp to 'id' via "'id' as keyof T" is
unsafe and can produce an "undefined" key; change the function signature to
remove the unsafe default and make keyProp a required parameter (e.g., keyProp:
keyof T) so callers must supply a valid key for T, remove the cast "'id' as
keyof T", and keep the reducer logic but index with item[keyProp] (wrapped with
String(item[keyProp]) to ensure a string key); update all call sites to pass the
correct keyProp.
- Around line 8-9: The generic type T used in objectToArray is unconstrained but
the implementation spreads obj[k], so update the signature to constrain T to
object (e.g., change the generic to T extends object) so TypeScript allows
spreading; keep the parameter type Record<string, T> and the return type Array<T
& { __id__: string }> unchanged—just add the extends object constraint on T in
the objectToArray function declaration.
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/api.ts`:
- Around line 39-47: The reducer is writing to an "undefined" key when
action.payload lacks scope or status; update the handlers for
t.API_REQUEST_START (and the similar handlers for request success/failure) to
guard: only compute and set status like {[String(scope)]: status} when scope is
neither null/undefined and status is defined, otherwise return the previous
state unchanged; locate the switch cases that currently set status (handlers
referencing action.payload, scope, status, error) and add a simple null-check on
scope/status before mutating state to prevent storing undefined keys/values.
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/auto_follow_pattern.ts`:
- Around line 37-47: The function setActiveForIds currently shallow-copies the
byId map but mutates nested objects (shallowCopyByIds[id].active = active),
violating Redux immutability; fix it by creating new objects for each id instead
of mutating the referenced object: iterate ids and for each id assign
shallowCopyByIds[id] = { ...byId[id], active } (or skip/handle missing ids) so
both the map and the individual ParsedAutoFollowPattern objects are new
instances before returning the new Record.
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/stats.ts`:
- Around line 37-40: The reducer handling success(t.AUTO_FOLLOW_STATS_LOAD)
blindly casts action.payload to AutoFollowStats and destructures it, which will
throw if payload is undefined; update the case in the reducer to first guard
that action.payload exists (e.g. if (!action.payload) return state) before
casting/destructuring (payload, recentAutoFollowErrors, rest) so the reducer
safely no-ops when payload is missing and only processes when payload is
present.
---
Nitpick comments:
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/components/form_entry_row.tsx`:
- Around line 143-149: The ternary in the error prop inside FormEntryRow is
redundant: the inner branch `Array.isArray(error) ? error : error` always yields
`error`; update the expression in the component (the variables `structured` and
`error` in form_entry_row.tsx, where the prop `error={... as ReactNode}` is set)
to simply choose `structured.message` when present and otherwise `error` (e.g.,
use a single conditional: structured && structured.message !== undefined ?
structured.message : error) and keep the ReactNode cast as before.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: 5ec990c6-0bb0-485d-b620-7c8fe5298817
⛔ Files ignored due to path filters (3)
x-pack/platform/plugins/private/cross_cluster_replication/public/app/components/__snapshots__/auto_follow_pattern_form.test.tsx.snapis excluded by!**/*.snapx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/__snapshots__/follower_index_form.test.tsx.snapis excluded by!**/*.snapx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/__snapshots__/auto_follow_pattern_validators.test.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (130)
x-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/auto_follow_pattern_add.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/auto_follow_pattern_edit.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/auto_follow_pattern_list.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/fixtures/auto_follow_pattern.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/fixtures/follower_index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/follower_index_add.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/follower_index_edit.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/follower_indices_list.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_add.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_edit.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/constants.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_add.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_edit.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/home.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/http_requests.jsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/http_requests.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/render.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/setup_environment.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/home.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/app.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_action_menu/auto_follow_pattern_action_menu.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_action_menu/auto_follow_pattern_action_menu.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_form.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_form.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_page_title.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_request_flyout.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/follower_index_actions_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/follower_index_pause_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/follower_index_resume_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/follower_index_unfollow_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/advanced_settings_fields.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/follower_index_request_flyout.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_page_title.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/form_entry_row.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/index.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/remote_clusters_form_field.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/remote_clusters_provider.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/section_error.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/section_loading.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/section_unauthorized.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/constants/sections.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/auto_follow_pattern_add.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/auto_follow_pattern_add.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_add/follower_index_add.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_add/follower_index_add.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_add/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_edit/follower_index_edit.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_edit/follower_index_edit.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_edit/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/auto_follow_pattern_table.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/auto_follow_pattern_table.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/home.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/home.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/index.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/api.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_errors.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_errors.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_pattern.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_pattern.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_pattern_validators.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_pattern_validators.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/follower_index_default_settings.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/follower_index_default_settings.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/get_remote_cluster_name.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/get_remote_cluster_name.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/input_validation.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/notifications.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/routing.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/routing.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/track_ui_metric.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/action_types.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/api.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/api.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/auto_follow_pattern.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/ccr.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/follower_index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/index.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/api.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/api.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/auto_follow_pattern.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/auto_follow_pattern.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/follower_index.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/follower_index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/stats.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/stats.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/selectors/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/store.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/store.ts
💤 Files with no reviewable changes (14)
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/components/index.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/get_remote_cluster_name.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/follower_index_default_settings.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/index.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/routing.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/stats.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/jest/client_integration/helpers/http_requests.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/index.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/follower_index.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/store.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/api.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/auto_follow_pattern.js
|
🧠 Learnings used✅ Actions performedFull review triggered. |
📝 WalkthroughWalkthroughThis pull request converts the Cross-Cluster Replication (CCR) plugin from JavaScript to TypeScript across all layers. Changes include migrating test files with new type annotations, converting helper modules to TypeScript with explicit return/parameter types, replacing PropTypes with TypeScript interfaces in React components, adding typed Redux actions and reducers, and converting service utilities with proper type definitions. Old ✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
x-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_edit/follower_index_edit.tsx (1)
148-175:⚠️ Potential issue | 🟠 MajorRendering an object as ReactNode will display
[object Object].When
statusCode === 404,errorMessagebecomes{ error: "..." }(lines 150-158), but it's then cast and rendered directly in the<p>tag at line 175. This will display[object Object]instead of the intended message.Proposed fix
- body={<p>{errorMessage as unknown as ReactNode}</p>} + body={<p>{typeof errorMessage === 'object' && errorMessage !== null && 'error' in errorMessage ? (errorMessage as { error: ReactNode }).error : (errorMessage as unknown as ReactNode)}</p>}Or restructure the error handling to always produce a
ReactNode:const errorMessage = error.body.statusCode === 404 - ? { - error: i18n.translate( + ? i18n.translate( 'xpack.crossClusterReplication.followerIndexEditForm.loadingErrorMessage', { defaultMessage: `The follower index ''{name}'' does not exist.`, values: { name }, } - ), - } + ) : error;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@x-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_edit/follower_index_edit.tsx` around lines 148 - 175, The code is rendering an object as a ReactNode: when error.body.statusCode === 404 the variable errorMessage is set to { error: "..." } and then cast and rendered in the <p> causing “[object Object]”. Fix by making errorMessage a string or ReactNode instead of an object (update the conditional that assigns errorMessage in follower_index_edit.tsx to return the i18n.translate(...) string for the 404 branch and for the non-404 branch return a meaningful string like error.message or String(error)), and then render that string (or a proper React element) in the body prop instead of casting the object.x-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.tsx (1)
104-131:⚠️ Potential issue | 🟠 MajorRendering error object directly will display "[object Object]"
When
error.body.statusCode !== 404,errorMessageis assigned the rawerrorobject. Casting it toReactNodeand rendering it will produce garbage output in the UI.Proposed fix
const errorMessage = error.body.statusCode === 404 ? { error: i18n.translate( 'xpack.crossClusterReplication.autoFollowPatternEditForm.loadingErrorMessage', { defaultMessage: `The auto-follow pattern ''{name}'' does not exist.`, values: { name }, } ), } : error; const listNav = reactRouterNavigate(this.props.history, `/auto_follow_patterns`); return ( <EuiPageTemplate.EmptyPrompt color="danger" iconType="warning" title={...} - body={<p>{errorMessage as unknown as ReactNode}</p>} + body={ + <p> + {error.body.statusCode === 404 + ? (errorMessage as { error: string }).error + : i18n.translate( + 'xpack.crossClusterReplication.autoFollowPatternEditForm.loadingErrorGeneric', + { defaultMessage: 'An error occurred while loading the auto-follow pattern.' } + )} + </p> + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@x-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.tsx` around lines 104 - 131, The code assigns the raw error object to errorMessage when error.body.statusCode !== 404 and then renders it (casting to ReactNode), which yields “[object Object]”; update the error handling in the component so errorMessage is a string or React element (e.g., use error.message, combine statusCode and message, or JSON.stringify(error) into a readable string) instead of the raw object; modify the branch that sets errorMessage (the variable referencing error.body.statusCode and error) so the non-404 path produces a user-friendly string/JSX and keep rendering the result inside the <EuiPageTemplate.EmptyPrompt> body as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.ts`:
- Around line 11-17: The defaulting of keyProp to the casted 'id' in
arrayToObject is unsafe because when T does not include an 'id' property
multiple items become acc['undefined']; fix by removing the unsafe default and
require an explicit key property: change the signature of arrayToObject to
accept a keyProp parameter (e.g., keyProp: keyof T or generic K extends keyof T)
without a default, or constrain the generic so T must include an id (if that is
intended); update callers to pass the correct keyProp when calling arrayToObject
and adjust usages of arrayToObject to supply the explicit key to avoid silent
collisions on 'undefined'.
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/auto_follow_pattern.ts`:
- Around line 37-46: setActiveForIds currently shallow-copies the map but
mutates the nested entity objects and will throw if an id is missing; update
setActiveForIds to be fully immutable and missing-id safe by creating a new
result object, iterating ids, checking if byId[id] exists, and for each existing
entry assign a new object copy of the entity with active set to the provided
value (leaving non-existent ids ignored), then return the new map so neither
original map nor original entity objects are mutated.
---
Outside diff comments:
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.tsx`:
- Around line 104-131: The code assigns the raw error object to errorMessage
when error.body.statusCode !== 404 and then renders it (casting to ReactNode),
which yields “[object Object]”; update the error handling in the component so
errorMessage is a string or React element (e.g., use error.message, combine
statusCode and message, or JSON.stringify(error) into a readable string) instead
of the raw object; modify the branch that sets errorMessage (the variable
referencing error.body.statusCode and error) so the non-404 path produces a
user-friendly string/JSX and keep rendering the result inside the
<EuiPageTemplate.EmptyPrompt> body as before.
In
`@x-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_edit/follower_index_edit.tsx`:
- Around line 148-175: The code is rendering an object as a ReactNode: when
error.body.statusCode === 404 the variable errorMessage is set to { error: "..."
} and then cast and rendered in the <p> causing “[object Object]”. Fix by making
errorMessage a string or ReactNode instead of an object (update the conditional
that assigns errorMessage in follower_index_edit.tsx to return the
i18n.translate(...) string for the 404 branch and for the non-404 branch return
a meaningful string like error.message or String(error)), and then render that
string (or a proper React element) in the body prop instead of casting the
object.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: a8af1186-ded4-4436-b947-c91e28fe02ab
⛔ Files ignored due to path filters (3)
x-pack/platform/plugins/private/cross_cluster_replication/public/app/components/__snapshots__/auto_follow_pattern_form.test.tsx.snapis excluded by!**/*.snapx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/__snapshots__/follower_index_form.test.tsx.snapis excluded by!**/*.snapx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/__snapshots__/auto_follow_pattern_validators.test.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (130)
x-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/auto_follow_pattern_add.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/auto_follow_pattern_edit.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/auto_follow_pattern_list.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/fixtures/auto_follow_pattern.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/fixtures/follower_index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/follower_index_add.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/follower_index_edit.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/follower_indices_list.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_add.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_edit.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/constants.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_add.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_edit.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/home.helpers.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/http_requests.jsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/http_requests.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/render.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/helpers/setup_environment.tsx-pack/platform/plugins/private/cross_cluster_replication/public/__jest__/client_integration/home.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/app.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_action_menu/auto_follow_pattern_action_menu.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_action_menu/auto_follow_pattern_action_menu.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_form.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_form.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_page_title.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_request_flyout.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/follower_index_actions_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/follower_index_pause_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/follower_index_resume_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/follower_index_unfollow_provider.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_actions_providers/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/advanced_settings_fields.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.test.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/follower_index_request_flyout.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_form/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/follower_index_page_title.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/form_entry_row.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/index.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/remote_clusters_form_field.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/remote_clusters_provider.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/section_error.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/section_loading.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/components/section_unauthorized.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/constants/sections.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/auto_follow_pattern_add.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/auto_follow_pattern_add.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_add/follower_index_add.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_add/follower_index_add.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_add/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_edit/follower_index_edit.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_edit/follower_index_edit.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/follower_index_edit/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/auto_follow_pattern_table.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/auto_follow_pattern_table.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/follower_indices_list/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/home.container.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/home.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/home/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/index.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/api.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_errors.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_errors.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_pattern.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_pattern.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_pattern_validators.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/auto_follow_pattern_validators.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/follower_index_default_settings.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/follower_index_default_settings.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/get_remote_cluster_name.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/get_remote_cluster_name.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/input_validation.tsxx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/notifications.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/routing.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/routing.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/track_ui_metric.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/action_types.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/api.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/api.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/auto_follow_pattern.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/ccr.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/follower_index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/index.d.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/api.test.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/api.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/auto_follow_pattern.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/auto_follow_pattern.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/follower_index.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/follower_index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/stats.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/stats.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/selectors/index.tsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/store.jsx-pack/platform/plugins/private/cross_cluster_replication/public/app/store/store.ts
💤 Files with no reviewable changes (14)
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/components/index.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/jest/client_integration/helpers/http_requests.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/sections/index.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/auto_follow_pattern.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/index.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/get_remote_cluster_name.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/routing.d.ts
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/follower_index.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/reducers/stats.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/store.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/follower_index_default_settings.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/services/utils.js
- x-pack/platform/plugins/private/cross_cluster_replication/public/app/store/actions/api.js
777d635 to
cc617f4
Compare
bd057aa to
2ce707f
Compare
|
|
||
| export type CcrApiError = Error | IHttpFetchError<ResponseErrorBody>; | ||
|
|
||
| export const toCcrApiError = (error: unknown): CcrApiError => { |
There was a problem hiding this comment.
For reviewers: we normalize unknown thrown values into a real Error (toCcrApiError) and then narrow fetch errors via isHttpFetchError so UI code can safely read response.status / body.statusCode and body.message. This avoids leaking non-Error objects into rendering (previously could trigger "Objects are not valid as a React child") and makes error display consistent across CCR.
| if (isUsingAdvancedSettings) { | ||
| uiMetrics.push(UIM_FOLLOWER_INDEX_USE_ADVANCED_OPTIONS); | ||
| } | ||
| const { status: _status, shards: _shards, ...body } = followerIndex as FollowerIndex; |
There was a problem hiding this comment.
For reviewers: createFollowerIndex intentionally strips status/shards from the POST payload. Those are response-only fields on FollowerIndex, and the server route schema rejects them (we reproduced a runtime failure: "Additional properties are not allowed ('status' was unexpected)"). This keeps the request aligned with the route contract and fixes follower-index creation.
| // Expect an error in the shape provided by Angular's $http service. | ||
| if (error && error.body) { | ||
| } catch (error: unknown) { | ||
| const apiError = toCcrApiError(error); |
There was a problem hiding this comment.
For reviewers: permission-check error handling now prefers ResponseErrorBody.message when present (falls back to Error.message), using the shared CCR error helpers. This slightly changes the displayed text in some failure modes (more precise server message) while keeping fatal-errors for non-HTTP exceptions.
|
Pinging @elastic/kibana-management (Team:Kibana Management) |
Both branches of the previous ternary returned `error.message`, so collapse it to a single expression. Made-with: Cursor
Pass the accumulator type to `reduce` so the seed `{}` no longer needs an
`as Record<string, T>` cast.
Made-with: Cursor
`defaultProps` was carried over from the previous test helper but no caller passes it, so remove the option and the corresponding spread. Made-with: Cursor
A short JSDoc comment so the next reader does not have to infer the intent from the `value === undefined ||` short-circuit. Made-with: Cursor
The local `RemoteCluster` interface was duplicating fields already exported as `RemoteClusterRow` from `services/api`. Import and use that type instead so the shape stays in sync with the API. Made-with: Cursor
All call sites already pass `title`, so the prop is required. Removing the optional marker also removes the non-null assertion in JSX, so the component cannot crash on a missing title element. Made-with: Cursor
`FollowerIndexEdit` already destructures `shards` out of the data it hands to the form, so narrow `FollowerIndexForm.followerIndex` to `Omit<FollowerIndex, 'shards'>` and remove the matching `as FollowerIndex` cast at the call site. The form's own `shards` destructuring becomes dead and is removed. Made-with: Cursor
Annotate `getTableColumns` and `search` with the matching `EuiInMemoryTableProps<ParsedAutoFollowPattern>` slices, set `type: 'icon'` on each row action so EUI can pick the icon-action variant, and type `onSearch` with `EuiSearchBarOnChangeArgs`. With those in place the `as` casts at the `<EuiInMemoryTable>` site are unnecessary. Made-with: Cursor
Annotate `getTableColumns`, the row `actions` array, and `search` with the matching `EuiInMemoryTableProps<FollowerIndexWithPausedStatus>` slices, set `type: 'icon'` on each row action, type `onSearch` with `EuiSearchBarOnChangeArgs`, and coerce `item.isPaused` to a boolean for the `available` predicate. This removes the `as` casts at the `<EuiInMemoryTable>` site. Made-with: Cursor
Move the null-check-and-throw out of every consumer and into a single `reactRouterOrThrow` getter on the routing service, switch the backing field to a JS private field (`#reactRouter`) so it cannot be reached from outside the class, and update consumers (forms, tables, detail panels, resume provider, routing test mock) to read through the new getter or the existing `reactRouter` accessor instead of the underscore prefixed field. Made-with: Cursor
Make `arrify` and `removeEmptyFields` generic so callers no longer need `as T[]` casts at the use site, and remove the unused `wait` helper. The pause/resume/unfollow follower-index providers drop their now redundant `arrify(...) as ...` casts. Made-with: Cursor
Pass dispatch/own prop generics to `connect` and split the dispatch prop shape into a named `DispatchProps` type so the wrapper inherits its public surface from the typed connect call instead of an `as ComponentType<OwnProps>` cast. Made-with: Cursor
…signment `_toasts` and `_fatalErrors` are only set by `init()`; lying to the type system with a definite-assignment assertion lets callers fail with a confusing "cannot read properties of undefined" later. Mark them explicitly optional and throw a descriptive error from `getToasts` / `getFatalErrors` if they are read before `init()` ran. Made-with: Cursor
Switch `FormEntryRow.onValueUpdate` to receive the parsed scalar value and let each call site decide which field key to write. This drops the unsafe `as Partial<FollowerIndexFormFields>` casts in `FollowerIndexForm` and lets the caller fan into either `name`, `leaderIndex`, or one of the advanced settings without rebuilding an intermediate object. While here, extract `StructuredError` and an `isStructuredError` type guard, widen `value` to `string | number | undefined` to match the underlying inputs, replace the form's `reduce`-with-cast in `getFieldsErrors` with a typed `for..of`, and drop the redundant `status`/`shards` stripping that the form's own field whitelist already covers. Made-with: Cursor
💔 Build Failed
Failed CI StepsTest Failures
Metrics [docs]Module Count
Async chunks
Page load bundle
Unknown metric groupsESLint disabled line counts
Total ESLint disabled count
History
|
The ES client typings for `CcrResumeFollowRequest` move the advanced settings (`max_outstanding_*`, `max_read_request_*`, etc.) to top-level parameters and disallow them inside `body`. Spread the serialized settings directly into the request and update the matching jest expectation. The HTTP wire format is unchanged. Made-with: Cursor
* main: (114 commits) Fix observability_ai_assistant_tool_call EBT error when connector is an inference endpoint (elastic#263334) init on install (elastic#263732) [One Workflow] fail-fast TaskRecovery for interrupted runs (elastic#261275) [Entity Store] Reset state error after successful task run (elastic#263087) [api-docs] 2026-04-19 Daily api_docs build (elastic#264280) [UII] Fix integration card row height calculation (elastic#264212) [scout] migrate FTR logstash api tests (elastic#262953) [StorageIndexAdapter] Set auto_expand_replicas to fix yellow health on single-node ES clusters (elastic#263096) [api-docs] 2026-04-18 Daily api_docs build (elastic#264260) [Scout] Update test config manifests (elastic#264257) [Security Solution][Detection Engine] enables AI rule creation feature flag (elastic#264036) [dashboards as code] only validate id on PUT route when creating new dashboard (elastic#264161) chore(NA): bump version to 9.5.0 (elastic#262165) skip failing test suite (elastic#263649) skip failing test suite (elastic#264236) [Discover] Convert remaining Enzyme tests to RTL (elastic#259676) auto-implement: Labels in model endpoints table of the model details flyout look misaligned (elastic#263770) [ci] Promote ES docker image after verification (elastic#263890) [Observability:Onboarding] Remove suppress global announcements that was breaking ensemble tests (elastic#264169) [Cases][AttachmentV2] Migrate persistable state part 2 - ML and AIOps charts (elastic#262597) ...
ff94f62 to
e131578
Compare
|
@SoniaSanzV @damian-polewski — your review surfaced a handful of recurring sharp edges from the migration (extra These are five small, targeted commits — each touches 1-2 files, largest is ~80 lines net, no architectural changes or new scope. Kept separate from the comment-driven ones so you can skim them quickly:
Thanks again for the thorough review — it caught patterns I'd missed and gave me the lens for these follow-ups. |
SoniaSanzV
left a comment
There was a problem hiding this comment.
thank you for addressing the feedback and the other improvements! LGTM!
damian-polewski
left a comment
There was a problem hiding this comment.
Thanks @kapral18 for addressing all the issues and adding improvements! LGTM and great job!
💚 Build Succeeded
Metrics [docs]Module Count
Async chunks
Page load bundle
|
Closes #239613.
Summary
.d.tsstubs in the migrated area.public/updates required by the migration chain: CCRcommonserialization typing alignment, one CCR server route typing/payload alignment, tsconfig/moon metadata updates, and CCR functional/a11y test typing updates.Notable runtime fixes/changes
CcrApiErrorhelpers so rendering/notification paths handle non-Errorthrowables safely and extract status/message consistently.createAutoFollowPatternandupdateAutoFollowPattern, so the update path only sends fields the route'sunknowns: 'forbid'schema accepts and no longer 400s on extra fields carried on the form/state object.error.response?.status ?? error.body?.statusCode, so 403 responses correctly flag the API as unauthorized in selectors that gate UI affordances.routing.reactRouterOrThrow(backed by a JS private#reactRouterfield), so consumers that try to read the router before it is set get a clear error instead of silently null-derefing inside JSX._toasts/_fatalErrors) with runtime checks that throw'CCR notifications service has not been initialized', surfacing init order bugs at the access site instead of as a misleadingcannot read 'add' of undefined.FormEntryRow'stitleprop required at the type boundary and drops thetitle!non-null assertion in JSX, so a caller forgetting to passtitlebecomes a type error instead of a runtime crash.Commit structure
lint_ts_projects, moon regeneration, eslint) kept separate.Test plan
node scripts/type_check --project x-pack/platform/plugins/private/cross_cluster_replication/tsconfig.json✅node scripts/jest x-pack/platform/plugins/private/cross_cluster_replication✅ (36 suites, 213 tests)node scripts/check_changes.ts✅Assisted with Cursor